跳到主要内容

12 GPT PWM输出实验

在这里插入图片描述

开发板官网https://www.edevkit.com/)

本系列教程目录:


GPT PWM 输出实验

本章目标:

  • 了解 RA6M5 处理器的 GPT 外设;
  • 学会使用 RASC 配置 GPT 实现 PWM 输出;

硬件设计

本实验使用开发板的 GPT 定时器外设,通过 PWM 输出通道输出方波信号,可使用示波器观察。

软件设计

新建工程

复制一份“07 SCI-UART_Recv_send”修改文件夹名“12 GPT_PWM_Timer”,双击打开 EBF_RA6M5.uvprojx 工程,通过 Keil 的新建文件新建 gpt_timer.cgpt_timer.h,保存到目录下的 \src 文件夹下。

FSP 配置

Keil 界面选择“Tools”→“RA Smart Configurator”打开 RASC 界面。

PWM 输出需要使用 IO 引脚进行输出,需要先在“Pins”配置页中为 GPT 配置引脚,将 GPT6 的 GTIOC6B 信号输出连接到 P600 引脚。

插图01

添加 GPT Stack 模块。

插图02

插图03

需要更改的配置如下:

Pin Output Support:配置允许输出 PWM 信号到引脚,使能引脚输出。

Name 和 Channel:这两项分别设置 GPT 模块名字为 g_timer_gpt6 和选择第 6 个 GPT 定时器(第 6 个通道)。

Mode:配置 GPT 的工作模式为 PWM 输出模式。

Period 和 Period Unit:将 PWM 频率设为 20 KHz,因此“Period”设置为 20,单位“Period Unit”设置为 Kilohertz,即千赫兹(KHz)。

GTIOCB Output Enabled:使能 GTIOCB 输出。

GTIOCB Stop Level:设置定时器停止时 GTIOCB 输出的电平为低电平。

GTIOC6B:选择连接到 P600 引脚,这个软件会自动设置。

GPT 的“Output”部分的属性描述:

属性描述
Custom Waveform > GTIOA/GTIOB > Initial Output Level设置 GPT 初始化时 GTIOCxA/GTIOCxB 的电平(低电平或高电平)。
Custom Waveform > GTIOA/GTIOB > Cycle End Output Level完成一个计数周期时 GTIOCxA/GTIOCxB 的输出电平(保持不变、输出高、输出低或反转电平)。
Custom Waveform > GTIOA/GTIOB > Compare Match Output Level发生比较匹配时 GTIOCxA/GTIOCxB 的输出电平(保持不变、输出高、输出低或反转电平)。
Custom Waveform > GTIOA/GTIOB > Retain Output Level at Count Stop在计数停止时保持 GTIOCxA/GTIOCxB 电平。
Custom Waveform > Custom Waveform Enable使能自定义波形的配置。
Duty Cycle Percent (only applicable in PWM mode)设定 PWM 占空比(仅用于 PWM 模式)
GTIOCA Output Enabled使能 GTIOCA 输出到相应引脚
GTIOCA Stop Level当 GPT 定时器停止时 GTIOCA 的输出电平
GTIOCB Output Enabled使能 GTIOCB 输出到相应引脚
GTIOCB Stop Level当 GPT 定时器停止时 GTIOCB 的输出电平

配置完成之后可以按下快捷键“Ctrl + S”保存,最后点击 “Generate Project Content” 按钮,让软件自动生成配置代码即可。

  1. GPT 的引脚信息

使用 GPT 往 P600 引脚输出 PWM,使用 RASC 配置 GPT 的通道且指定引脚后,生成的工程中的 pin_data.c 中的 g_bsp_pin_cfg_data[] 数组就会添加该引脚的配置信息。

const ioport_pin_cfg_t g_bsp_pin_cfg_data[] = {
......(省略内容)
{.pin = BSP_IO_PORT_06_PIN_00,
.pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN
| (uint32_t) IOPORT_PERIPHERAL_GPT1)
},
};
  1. GPT配置信息

GPT 模块的配置信息在 hal_data.c 中以 timer_cfg_t 类型的结构体变量表示。

const timer_cfg_t g_timer_gpt6_cfg =
{
.mode = TIMER_MODE_PWM,
/* Actual period: 0.00005 seconds. Actual duty: 50%. */
.period_counts = (uint32_t) 0x1388,
.duty_cycle_counts = 0x9c4,
.source_div = (timer_source_div_t)0,
.channel = 6,
.p_callback = NULL,
/** If NULL then do not add & */
#if defined(NULL)
.p_context = NULL,
#else
.p_context = &NULL,
#endif
.p_extend = &g_timer_gpt6_extend,
.cycle_end_ipl = (BSP_IRQ_DISABLED),
#if defined(VECTOR_NUMBER_GPT6_COUNTER_OVERFLOW)
.cycle_end_irq = VECTOR_NUMBER_GPT6_COUNTER_OVERFLOW,
#else
.cycle_end_irq = FSP_INVALID_VECTOR,
#endif
};

mode 表示 GPT 的类型,此处是 PWM;

第 05~06 行:表示输出 PWM 的周期和占空比;

channel 表示使用的 GPT 的通道;

使用 GPT 的 open 函数打开 GPT 设备时,就会使用这些配置信息初始化 GPT。

程序设计

实现 GPT 的 PWM 输出功能,开启 P600 通道的 PWM,设置输出的占空比,接入示波器查看波形占空比,改变占空比,观察波形变化。

  1. 打开 GPT 设备
R_GPT_Open(timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg);

p_ctrltimer_ctrl_t 结构体指针参数,本质是一个 void 类型的参数,指向 st_gpt_instance_ctrl 类型变量;

p_cfgtimer_cfg_t 结构体指针参数,在程序中会指向在 hal_data.c 中定义的 g_timer_cfg 静态全局变量;

  1. 开启/停止 GPT 计数
R_GPT_Start(timer_ctrl_t * const p_ctrl);
R_GPT_Stop(timer_ctrl_t * const p_ctrl);

必须要在 GPT 打开状态下使用这两个函数。

  1. 设置 GPT 输出 PWM 的占空比
R_GPT_DutyCycleSet(timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin);

在 PWM 驱动应用中,使用此函数来修改占空比,最后一个参数是指 GPT 的输出通道,而不是指 IO 引脚。

程序编写

gpt_pwm.h 头文件里定义初始化函数,设置占空比函数。

#ifndef __BSP_GPT_PWM_OUTPUT_H
#define __BSP_GPT_PWM_OUTPUT_H
#include "hal_data.h"

void gpt_PWM_Init(void);

void gpt_PWM_SetDuty(uint8_t duty);

#endif

gpt_pwm.c 里实现初始化函数、设置占空比函数。

初始化函数里打开 GPT 设备并启动定时器。

设置占空比输入 0~100 数值,先获取 GPT 的周期计时数,换算占空比的计数值,再设置输出占空比值。

#include "gpt_pwm.h"

//PWM输出引脚 GTIOC6B P600


// GPT初始化函数
void gpt_PWM_Init(void)
{
// 初始化GPT模块
R_GPT_Open(&g_timer_gpt6_ctrl, &g_timer_gpt6_cfg);

// 启动GPT定时器
R_GPT_Start(&g_timer_gpt6_ctrl);

//设置占空比为 80%
gpt_PWM_SetDuty(80);
}


//设置PWM占空比 0~100
void gpt_PWM_SetDuty(uint8_t duty)
{
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;

//限制占空比范围:0~100
if (duty > 100)
duty = 100;

//获得GPT的信息
R_GPT_InfoGet(&g_timer_gpt6_ctrl, &info);

//获得计时器一个周期需要的计数次数
current_period_counts = info.period_counts;

//根据占空比和一个周期的计数次数计算GTCCR寄存器的值
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts * duty) / 100);

//最后调用FSP库函数设置占空比
R_GPT_DutyCycleSet(&g_timer_gpt6_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCB);
}

hal_entry.c 文件中添加头文件 gpt_pwm.h,在 hal_entry 入口函数初始化 GPT。

void hal_entry(void)
{
/* TODO: add your own code here */

led_Init(); // LED 初始化
uart0_Init();
gpt_PWM_Init();
printf("start PWM test\r\n");

while(1)
{
LED1_TOGGLE();
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //延时1秒
}


#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}

下载验证

连接下载器,将程序编译并下载到开发板之后,按下复位按键来复位开发板,程序启动初始化完成。

通过示波器探头连接 P600 和 GND,观察示波器检测到方波,占空比 80%,频率 20K Hz。

插图04

修改占空比,设置为 50%,观察波形。

插图05